<?php
class database {
    static $instance;
    static $controler;
    public function __construct ($type,$connectNow=false) {
    	@define('DATABASE_TYPE',$type);
        require_once ('database/databaseInterface.php');
        require_once ('database/'.DATABASE_TYPE.'.php');
        $controler = 'databaseControler'.strToUpper($type);
        $this->controler=new $controler;
        if ($connectNow) $this->controler->connect (DB_HOST,DB_USER,DB_PASS,DB_BANK);
    }
    public function __call ($method,$args) {
        return call_user_func_array (array ($this->controler,$method),$args);
    }

    public function multipleQuery ($query,$subs=array ()) {
        foreach ($subs as $value) {
            if (gettype($value)=='string') {
            	$value=$this->quote_smart ($value);
                $sql=str_replace('?',$value,$query);
                $this->excecute ($sql);
            } elseif (gettype($value)=='array') {
                $temp=$query;
                foreach ($value as $v) $temp=preg_replace('/\?/',$this->quote_smart ($v),$temp,1);
                $sql=$temp;
                $this->excecute ($sql);
            }
        }
        return void;
    }
    public function detailTable ($table) {
      $query="SHOW FULL COLUMNS FROM `$table`";
      $result=$this->controler->excecute ($query,false);
      while ($this->controler->fetchInto(&$o,$result)) {
        $return[]=$o;
      }
      return $return;
    }
    public function __destruct () {
      $this->controler->desconecta ();
    }
    function getOne ($query,$typeResult='object',$returnClass='') {
        $resource=$this->excecute($query." LIMIT 1",false);
        $this->fetchInto(&$return,$resource,$typeResult,$returnClass);
        return $return;
    }
    /**
     * Alias para {@link getOne}, a diferença é que {@link justOne} auxilia na facilidade de uso.
     * <code>
     * $result=$sql->justOne ('clientes',12);
     * </code>
     * O método considerará o segundo parâmetro como id=12 por se tratar de um número.
     * <code>
     * $result=$sql->justOne ('pessoas','`cpf`="22233366637"','nome');
     * </code>
     * Como você pode perceber não é necessário o uso de inteiro para o segundo parâmetro ou mesmo usar sempre
     * o id como campo de busca.
     * É possível que definamos quais campos da tabela desejamos retornar usando o
     * terceiro parâmetro: um array associativo contendo 'campos' como a lista de colunas que desejamos obter
     * como resultado.
     * Não se esqueça que você tem a opção de usar o método quote_smart para prevenir-se de SQL injections:
     * <code>
     * $clienteBusca=$sql->quote_smart ($_POST['cliente']);
     * $cliente=$sql->justOne ('clientes',"cliente=$clienteBusca");
     * </code>
     *
     * @param string $table
     * @param int|string $where
     * @param array $options
     * @return array|object
     */
    public function justOne ($table,$where,$campos=null,$typeResult='object',$returnClass='')  {
        if (!$this->tableExists($table)) return false;
        $campos=$campos?$campos:'*';
        $where=gettype($where)=='number'?' id ='.$where:$where;
        $query="SELECT $campos FROM $table WHERE $where";
        return $this->getOne ($query,$typeResult,$returnClass);
    }
    /**
     * Adicionar
     * insere uma nova linha na tabela com base em um array associativo.
     * <code>
     * $dados=array (
     *      'nome'=>'Miguel',
     *      'idade'=>12,
     *      'peso'=>96.4,
     *      'estadocivil'=>'casado'
     * );
     * $sql->adicionar ('clientes',$dados):
     * $dados['nome']='André';
     * </code>
     * Não há necessidade de inserir um id, levando em conta que o id é o primary key e tem sua propriedade
     * como auto_increment normalmente.
     *
     * @param string $tabela
     * @param array $dados
     * @param bool $recordResult
     * @return object|resource
     */
    public function adicionar ($tabela,$dados) {
        if ((is_array($dados)) && ( $this->tableExists($tabela) ) ) {
            $keys='';
            foreach ($dados as $k=>$v) {
                $keys.=(substr($keys,-1)=="`"?",":"") . "`$k`";
                $values.=($v=='NOW ()'?" NOW()":" '$v'").",";
            }
            $values=substr($values,0,-1);
            return $this->excecute ( "INSERT INTO `$tabela` ($keys) VALUES ($values)");
        }
        return false;
    }
    /**
     * <code>
     * $dados = array (
     *   array ('MG','Minas Gerais'),
     *   array ('CE','Ceará'),
     *   array ('BA','Bahia')
     * );
     * $database->multiAdicionar ('estados','`uf`,`estado`',$dados);
     * </code>
     */
    public function multiAdicionar ($tabela,$campos,$valores=array ()) {
      $conta=count (explode (',',$campos));
      $values=implode (',',array_fill (0,$conta,'?'));
      $query="INSERT INTO $tabela ($campos) VALUES ($values)";
      $this->multipleQuery ($query,$valores);
      //print_r ($values);
    }
    /**
     * Deleta uma ou mais linhas da tabela, dependendo do where
     *
     * @param string $table
     * @param int|string $where Pode ser um inteiro, baseando-se em id ou uma comparação como pessoa_id=12
     */
    public function remover ($table,$where=false,$limit='LIMIT 1') {
        if ($this->tableExists($table)) {
            if ($where) $where='WHERE '.(gettype($where)=='integer'?'id = "'.$where.'"':$where);
            $query="DELETE FROM $table $where $limit";
            return $this->excecute($query,false);
        }
        return false;
    }
    /**
     * Faz o update em uma tabela com base em seu search que pode ser um inteiro ou um campo comparativo como user='michael'
     * <code>
     * $dados=array (
     *   'cor'=>vermelho
     * );
     * $sql->uptate ('carros',$dados,12);
     * </code>
     *
     * @param string $tabela
     * @param array $dados No formato array ('coluna'=>'valor')
     * @param {string|int} $search Se for int, remeterá ao id, mas você pode especificar uma condição como user='mike'
     * @return object
     */
    function update ($tabela,$dados,$search) {
        if ((is_array($dados)) && ( $this->tableExists ($tabela) ) ) {
            $query='';
            foreach ($dados as $k=>$v) {
                $query.=($query?", ":"")."`$k`='$v'";
            }
            $search=(gettype($search)=='integer'?'`id`=':'').$search;
            return $this->excecute ("UPDATE `$tabela` SET $query WHERE $search",false);
        }
        return false;
    }
}
?>